package com.nulldev.util.data.legacy;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.SecureRandom;

import com.nulldev.util.JVM.JVM;
import com.nulldev.util.VariableAPI.util.random.GlobalRandom;
import com.nulldev.util.data.Variables;

public class CloneUtils {
	public static Object clone(final Object obj) {
		try {
			Object clone = obj.getClass().newInstance();
			for (Field field : obj.getClass().getDeclaredFields()) {
				field.setAccessible(true);
				field.set(clone, field.get(obj));
			}
			return clone;
		} catch (Exception e) {
			JVM.errorln(e);
			return null;
		}
	}

	public static Object cloneObject(Object obj) {
		try {
			Object clone = obj.getClass().newInstance();
			for (Field field : obj.getClass().getDeclaredFields()) {
				field.setAccessible(true);
				if (field.get(obj) == null || Modifier.isFinal(field.getModifiers())) {
					continue;
				}
				if (field.getType().isPrimitive() || field.getType().equals(String.class) || field.getType().getSuperclass().equals(Number.class)
						|| field.getType().equals(Boolean.class)) {
					field.set(clone, field.get(obj));
				} else {
					Object childObj = field.get(obj);
					if (childObj == obj) {
						field.set(clone, clone);
					} else {
						field.set(clone, cloneObject(field.get(obj)));
					}
				}
			}
			return clone;
		} catch (Exception e) {
			JVM.errorln(e);
			return null;
		}
	}

	public static BufferedImage clone(final BufferedImage in) {
		final BufferedImage out = new BufferedImage(in.getWidth(), in.getHeight(), in.getType());
		final Graphics2D g2d_out = (Graphics2D) out.getGraphics();
		for (int x = 0; x < in.getWidth(); x++) {
			for (int y = 0; y < in.getHeight(); y++) {
				g2d_out.setColor(new Color(in.getRGB(x, y)));
				g2d_out.fillRect(x, y, 1, 1);
			}
		}
		return out;
	}

	public static BufferedImage deepCopy(final BufferedImage bi) {
		final ColorModel cm = Variables.requireNonNullObject(bi, "bi").getColorModel();
		final boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
		final WritableRaster raster = bi.copyData(bi.getRaster().createCompatibleWritableRaster());
		return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
	}

	public static String[] createBuffer(final int junkSize) {
		final String[] o = new String[junkSize];
		final SecureRandom sr = GlobalRandom.getGlobalInsecureRandom();
		for (int i = 0; i < o.length; i++) {
			o[i] = String.valueOf(sr.nextInt());
		}
		return o;
	}
}
